#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
GitLab Legacy 模块

包含从原有脚本迁移过来的功能：
- GitLabCommitsAnalyzer: 提交记录分析器
- GitLabReposFetcher: 仓库信息获取器  
- GitLabUsersCollector: 用户信息收集器

这些类保持与原有脚本的兼容性，同时集成到新的包结构中。
"""

import csv
import json
import random
import time
from datetime import datetime
from typing import Dict, List, Optional
from urllib.parse import quote_plus

import matplotlib.pyplot as plt
import pandas as pd
import requests
from loguru import logger

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


class GitLabCommitsAnalyzer:
    """GitLab提交记录分析器（从原gitlab_commits_analyzer.py迁移）"""

    def __init__(self, access_token: str, gitlab_url: str = "http://gitlab.waterism.com:8888"):
        """
        初始化GitLab提交分析器
        
        Args:
            access_token: GitLab访问令牌
            gitlab_url: GitLab实例URL
        """
        self.access_token = access_token
        self.gitlab_url = gitlab_url.rstrip('/')
        self.base_url = f"{self.gitlab_url}/api/v4"
        self.session = requests.Session()

        # 设置请求头
        self.session.headers.update({
            'User-Agent': 'GitLab-Python-Client/1.0',
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'PRIVATE-TOKEN': self.access_token
        })

    def get_repo_commits(self, project_id: str, **kwargs) -> List[Dict]:
        """
        获取项目的提交记录
        
        Args:
            project_id: 项目ID或路径
            **kwargs: 其他查询参数
                - ref_name: 分支名称 (默认为默认分支)
                - since: 开始时间 (ISO 8601格式)
                - until: 结束时间 (ISO 8601格式)
                - path: 文件路径过滤
                - author: 作者过滤
                - per_page: 每页数量 (1-100, 默认20)
                - page: 页码 (默认1)
        
        Returns:
            提交记录列表
        """
        # 对项目ID进行URL编码，支持路径格式的项目ID
        encoded_project_id = quote_plus(str(project_id))
        url = f"{self.base_url}/projects/{encoded_project_id}/repository/commits"

        # 构建查询参数
        params = {}

        # 添加可选参数
        optional_params = ['ref_name', 'since', 'until', 'path', 'author', 'per_page', 'page']
        for param in optional_params:
            if param in kwargs and kwargs[param]:
                params[param] = kwargs[param]

        logger.info(f"GitLab API请求: {url}")
        logger.info(f"请求参数: {params}")
        logger.info(f"项目ID: {project_id}")

        # 首先检查项目是否为空仓库
        try:
            project_info_url = f"{self.base_url}/projects/{encoded_project_id}"
            project_response = self.session.get(project_info_url)
            if project_response.status_code == 200:
                project_data = project_response.json()
                if project_data.get('empty_repo', False):
                    logger.warning(f"项目 {project_id} 是空仓库，没有提交记录")
                    return []
            else:
                logger.warning(f"无法获取项目信息，状态码: {project_response.status_code}")
        except Exception as e:
            logger.warning(f"检查项目信息时出错: {e}")

        try:
            response = self.session.get(url, params=params)
            response.raise_for_status()

            commits = response.json()
            logger.info(f"成功获取 {len(commits)} 个提交记录")

            # 添加随机延迟避免API限制
            time.sleep(random.uniform(0.1, 0.3))

            return commits

        except requests.exceptions.RequestException as e:
            logger.error(f"请求失败: {e}")
            if hasattr(e, 'response') and e.response is not None:
                logger.error(f"响应状态码: {e.response.status_code}")
                logger.error(f"响应内容: {e.response.text}")
            return []
        except json.JSONDecodeError as e:
            logger.error(f"JSON解析失败: {e}")
            return []

    def get_all_commits(self, project_id: str, **kwargs) -> List[Dict]:
        """
        获取项目的所有提交记录（分页获取）
        
        Args:
            project_id: 项目ID或路径
            **kwargs: 其他查询参数
        
        Returns:
            所有提交记录列表
        """
        all_commits = []
        page = 1
        per_page = kwargs.get('per_page', 100)  # 增加每页数量以减少请求次数

        while True:
            kwargs_copy = kwargs.copy()
            kwargs_copy.update({'page': page, 'per_page': per_page})

            commits = self.get_repo_commits(project_id, **kwargs_copy)

            if not commits:
                break

            all_commits.extend(commits)
            logger.info(f"已获取第 {page} 页，累计 {len(all_commits)} 个提交")

            # 如果返回的提交数少于每页数量，说明已经是最后一页
            if len(commits) < per_page:
                break

            page += 1

            # 添加延迟避免API限制
            time.sleep(random.uniform(0.2, 0.5))

        logger.info(f"总共获取 {len(all_commits)} 个提交记录")
        return all_commits

    def get_single_commit(self, project_id: str, commit_sha: str) -> Dict:
        """
        获取单个提交的详细信息
        
        Args:
            project_id: 项目ID或路径
            commit_sha: 提交SHA
        
        Returns:
            提交详细信息
        """
        encoded_project_id = quote_plus(str(project_id))
        url = f"{self.base_url}/projects/{encoded_project_id}/repository/commits/{commit_sha}"

        try:
            response = self.session.get(url)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"获取提交详情失败: {e}")
            return {}

    def get_user_by_email(self, email: str) -> Optional[Dict]:
        """
        根据邮箱获取用户信息
        
        Args:
            email: 用户邮箱
        
        Returns:
            用户信息字典，如果未找到则返回None
        """
        url = f"{self.base_url}/users"
        params = {'search': email}

        try:
            response = self.session.get(url, params=params)
            response.raise_for_status()
            users = response.json()

            # 查找匹配的用户
            for user in users:
                if user.get('email') == email or user.get('public_email') == email:
                    return {
                        'id': user.get('id'),
                        'username': user.get('username'),
                        'name': user.get('name'),
                        'email': user.get('email') or user.get('public_email'),
                        'avatar_url': user.get('avatar_url'),
                        'web_url': user.get('web_url')
                    }

            return None

        except requests.exceptions.RequestException as e:
            logger.error(f"获取用户信息失败: {e}")
            return None

    def get_project_branches(self, project_id: str) -> List[str]:
        """
        获取项目的所有分支
        
        Args:
            project_id: 项目ID或路径
        
        Returns:
            分支名称列表
        """
        encoded_project_id = quote_plus(str(project_id))
        url = f"{self.base_url}/projects/{encoded_project_id}/repository/branches"

        try:
            response = self.session.get(url)
            response.raise_for_status()
            branches = response.json()
            return [branch['name'] for branch in branches]
        except requests.exceptions.RequestException as e:
            logger.error(f"获取分支列表失败: {e}")
            return []

    def get_commit_statistics(self, project_id: str, **kwargs) -> Dict:
        """
        获取提交统计信息
        
        Args:
            project_id: 项目ID或路径
            **kwargs: 查询参数
        
        Returns:
            统计信息字典
        """
        commits = self.get_all_commits(project_id, **kwargs)

        if not commits:
            return {
                'total_commits': 0,
                'contributors': [],
                'date_range': {},
                'commit_frequency': {}
            }

        # 统计贡献者
        contributors = {}
        for commit in commits:
            author_email = commit.get('author_email', 'unknown')
            author_name = commit.get('author_name', 'Unknown')

            if author_email not in contributors:
                contributors[author_email] = {
                    'name': author_name,
                    'email': author_email,
                    'commits': 0
                }
            contributors[author_email]['commits'] += 1

        # 日期范围
        dates = [commit.get('created_at', '') for commit in commits if commit.get('created_at')]
        date_range = {}
        if dates:
            date_range = {
                'earliest': min(dates),
                'latest': max(dates)
            }

        return {
            'total_commits': len(commits),
            'contributors': list(contributors.values()),
            'date_range': date_range,
            'commit_frequency': self._calculate_commit_frequency(commits)
        }

    def _calculate_commit_frequency(self, commits: List[Dict]) -> Dict:
        """
        计算提交频率统计
        
        Args:
            commits: 提交记录列表
        
        Returns:
            频率统计字典
        """
        frequency = {
            'by_day': {},
            'by_hour': {},
            'by_weekday': {},
            'by_month': {}
        }

        for commit in commits:
            created_at = commit.get('created_at')
            if not created_at:
                continue

            try:
                dt = datetime.fromisoformat(created_at.replace('Z', '+00:00'))

                # 按日期统计
                date_key = dt.strftime('%Y-%m-%d')
                frequency['by_day'][date_key] = frequency['by_day'].get(date_key, 0) + 1

                # 按小时统计
                hour_key = str(dt.hour)
                frequency['by_hour'][hour_key] = frequency['by_hour'].get(hour_key, 0) + 1

                # 按星期统计
                weekday_key = dt.strftime('%A')
                frequency['by_weekday'][weekday_key] = frequency['by_weekday'].get(weekday_key, 0) + 1

                # 按月份统计
                month_key = dt.strftime('%Y-%m')
                frequency['by_month'][month_key] = frequency['by_month'].get(month_key, 0) + 1

            except Exception as e:
                logger.warning(f"解析日期失败: {created_at}, 错误: {e}")
                continue

        return frequency

    def get_student_level_statistics(self, project_ids: List[str], progress_callback=None,
                                     include_line_stats: bool = True, **kwargs) -> List[Dict]:
        """
        获取学生级别的统计信息（按学生聚合多个项目的数据）
        
        Args:
            project_ids: 项目ID列表
            progress_callback: 进度回调函数
            include_line_stats: 是否包含代码行数统计
            **kwargs: 其他查询参数
        
        Returns:
            学生统计信息列表
        """
        student_stats = {}
        total_projects = len(project_ids)

        for i, project_id in enumerate(project_ids):
            if progress_callback:
                progress_callback(i, total_projects, f"处理项目 {project_id}")

            logger.info(f"处理项目 {project_id} ({i + 1}/{total_projects})")

            try:
                commits = self.get_all_commits(project_id, **kwargs)

                for commit in commits:
                    author_email = commit.get('author_email', 'unknown')
                    author_name = commit.get('author_name', 'Unknown')

                    if author_email not in student_stats:
                        student_stats[author_email] = {
                            'name': author_name,
                            'email': author_email,
                            'total_commits': 0,
                            'projects': set(),
                            'first_commit': None,
                            'last_commit': None,
                            'total_additions': 0,
                            'total_deletions': 0,
                            'commit_details': []
                        }

                    student = student_stats[author_email]
                    student['total_commits'] += 1
                    student['projects'].add(str(project_id))

                    # 更新时间范围
                    commit_date = commit.get('created_at')
                    if commit_date:
                        if not student['first_commit'] or commit_date < student['first_commit']:
                            student['first_commit'] = commit_date
                        if not student['last_commit'] or commit_date > student['last_commit']:
                            student['last_commit'] = commit_date

                    # 获取详细的提交信息（包含代码行数）
                    if include_line_stats:
                        try:
                            detailed_commit = self.get_single_commit(project_id, commit['id'])
                            if detailed_commit:
                                stats = detailed_commit.get('stats', {})
                                student['total_additions'] += stats.get('additions', 0)
                                student['total_deletions'] += stats.get('deletions', 0)

                                student['commit_details'].append({
                                    'project_id': project_id,
                                    'commit_id': commit['id'],
                                    'title': commit.get('title', ''),
                                    'created_at': commit_date,
                                    'additions': stats.get('additions', 0),
                                    'deletions': stats.get('deletions', 0)
                                })
                        except Exception as e:
                            logger.warning(f"获取提交详情失败: {e}")

                    # 添加延迟避免API限制
                    time.sleep(random.uniform(0.05, 0.1))

            except Exception as e:
                logger.error(f"处理项目 {project_id} 时出错: {e}")
                continue

        # 转换为列表格式并计算额外统计信息
        result = []
        for email, stats in student_stats.items():
            stats['projects'] = list(stats['projects'])
            stats['project_count'] = len(stats['projects'])

            # 计算活跃天数
            if stats['first_commit'] and stats['last_commit']:
                try:
                    first_date = datetime.fromisoformat(stats['first_commit'].replace('Z', '+00:00'))
                    last_date = datetime.fromisoformat(stats['last_commit'].replace('Z', '+00:00'))
                    stats['active_days'] = (last_date - first_date).days + 1
                except Exception:
                    stats['active_days'] = 1
            else:
                stats['active_days'] = 1

            # 计算平均每日提交数
            stats['avg_commits_per_day'] = stats['total_commits'] / max(stats['active_days'], 1)

            result.append(stats)

        # 按总提交数排序
        result.sort(key=lambda x: x['total_commits'], reverse=True)

        if progress_callback:
            progress_callback(total_projects, total_projects, "处理完成")

        return result

    def get_student_level_statistics_by_projects(self, project_ids: List[str], progress_callback=None,
                                                 include_line_stats: bool = True, **kwargs) -> List[Dict]:
        """
        获取按项目分组的学生统计信息
        
        Args:
            project_ids: 项目ID列表
            progress_callback: 进度回调函数
            include_line_stats: 是否包含代码行数统计
            **kwargs: 其他查询参数
        
        Returns:
            按项目分组的学生统计信息
        """
        # 这里可以实现按项目分组的逻辑
        # 为了保持兼容性，暂时返回原有的统计结果
        return self.get_student_level_statistics(project_ids, progress_callback, include_line_stats, **kwargs)

    def commits_to_dataframe(self, commits: List[Dict]) -> pd.DataFrame:
        """
        将提交记录转换为DataFrame
        
        Args:
            commits: 提交记录列表
        
        Returns:
            DataFrame格式的提交数据
        """
        if not commits:
            return pd.DataFrame()

        # 提取关键字段
        data = []
        for commit in commits:
            try:
                # 解析日期
                created_at = commit.get('created_at', '')
                commit_date = None
                if created_at:
                    try:
                        commit_date = datetime.fromisoformat(created_at.replace('Z', '+00:00'))
                    except Exception:
                        pass

                data.append({
                    'id': commit.get('id', ''),
                    'short_id': commit.get('short_id', ''),
                    'title': commit.get('title', ''),
                    'message': commit.get('message', ''),
                    'author_name': commit.get('author_name', ''),
                    'author_email': commit.get('author_email', ''),
                    'authored_date': commit.get('authored_date', ''),
                    'committer_name': commit.get('committer_name', ''),
                    'committer_email': commit.get('committer_email', ''),
                    'committed_date': commit.get('committed_date', ''),
                    'created_at': created_at,
                    'web_url': commit.get('web_url', ''),
                    'commit_date': commit_date,
                    'date': commit_date.date() if commit_date else None,
                    'hour': commit_date.hour if commit_date else None,
                    'weekday': commit_date.weekday() if commit_date else None,
                    'month': commit_date.month if commit_date else None,
                    'year': commit_date.year if commit_date else None
                })
            except Exception as e:
                logger.warning(f"处理提交记录时出错: {e}")
                continue

        df = pd.DataFrame(data)

        # 设置日期相关的索引
        if 'commit_date' in df.columns and not df['commit_date'].isna().all():
            df = df.sort_values('commit_date')

        return df

    def analyze_commits(self, df: pd.DataFrame) -> Dict:
        """
        分析提交数据
        
        Args:
            df: 提交数据DataFrame
        
        Returns:
            分析结果字典
        """
        if df.empty:
            return {'error': '没有数据可分析'}

        analysis = {
            'total_commits': len(df),
            'unique_authors': df['author_email'].nunique(),
            'date_range': {
                'start': df['commit_date'].min(),
                'end': df['commit_date'].max()
            },
            'top_contributors': df['author_email'].value_counts().head(10).to_dict(),
            'commits_by_hour': df['hour'].value_counts().sort_index().to_dict() if 'hour' in df.columns else {},
            'commits_by_weekday': df[
                'weekday'].value_counts().sort_index().to_dict() if 'weekday' in df.columns else {},
            'commits_by_month': df.groupby(
                [df['year'], df['month']]).size().to_dict() if 'year' in df.columns and 'month' in df.columns else {}
        }

        return analysis

    def generate_report(self, project_id: str, **kwargs) -> pd.DataFrame:
        """
        生成项目提交报告
        
        Args:
            project_id: 项目ID
            **kwargs: 查询参数
        
        Returns:
            报告DataFrame
        """
        logger.info(f"开始生成项目 {project_id} 的提交报告")

        # 获取所有提交
        commits = self.get_all_commits(project_id, **kwargs)

        if not commits:
            logger.warning(f"项目 {project_id} 没有找到提交记录")
            return pd.DataFrame()

        # 转换为DataFrame
        df = self.commits_to_dataframe(commits)

        # 添加统计信息
        analysis = self.analyze_commits(df)
        logger.info(f"报告生成完成: {analysis['total_commits']} 个提交, {analysis['unique_authors']} 个贡献者")

        return df


class GitLabReposFetcher:
    """GitLab仓库信息获取器（从原gitlab_repos_fetcher.py迁移）"""

    def __init__(self, access_token: str, gitlab_url: str = "http://gitlab.waterism.com:8888"):
        """
        初始化GitLab API客户端
        
        Args:
            access_token: GitLab访问令牌
            gitlab_url: GitLab实例URL
        """
        self.access_token = access_token
        self.gitlab_url = gitlab_url.rstrip('/')
        self.base_url = f"{self.gitlab_url}/api/v4"
        self.session = requests.Session()

        # 设置请求头
        self.session.headers.update({
            'User-Agent': 'GitLab-Python-Client/1.0',
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'PRIVATE-TOKEN': self.access_token
        })

    def get_group_projects(self, group_id: str, **kwargs) -> List[Dict]:
        """
        获取群组的项目列表
        
        Args:
            group_id: 群组ID或路径
            **kwargs: 其他查询参数
        
        Returns:
            项目列表
        """
        # 对群组ID进行URL编码
        encoded_group_id = quote_plus(str(group_id))
        url = f"{self.base_url}/groups/{encoded_group_id}/projects"

        # 构建查询参数
        params = {
            'visibility': kwargs.get('visibility', 'private'),
            'order_by': kwargs.get('order_by', 'last_activity_at'),
            'sort': kwargs.get('sort', 'desc'),
            'per_page': kwargs.get('per_page', 20),
            'page': kwargs.get('page', 1)
        }

        # 添加可选参数
        optional_params = ['search', 'simple']
        for param in optional_params:
            if param in kwargs and kwargs[param] is not None:
                params[param] = kwargs[param]

        try:
            response = self.session.get(url, params=params)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"请求失败: {e}")
            if hasattr(e, 'response') and e.response is not None:
                logger.error(f"响应状态码: {e.response.status_code}")
                logger.error(f"响应内容: {e.response.text}")
            return []
        except json.JSONDecodeError as e:
            logger.error(f"JSON解析失败: {e}")
            return []

    def get_all_projects(self, **kwargs) -> List[Dict]:
        """
        获取所有可访问的项目
        
        Args:
            **kwargs: 查询参数
        
        Returns:
            项目列表
        """
        url = f"{self.base_url}/projects"

        # 构建查询参数
        params = {
            'visibility': kwargs.get('visibility', 'private'),
            'order_by': kwargs.get('order_by', 'last_activity_at'),
            'sort': kwargs.get('sort', 'desc'),
            'per_page': kwargs.get('per_page', 20),
            'page': kwargs.get('page', 1)
        }

        # 添加可选参数
        optional_params = ['search', 'simple', 'owned', 'membership', 'starred']
        for param in optional_params:
            if param in kwargs and kwargs[param] is not None:
                params[param] = kwargs[param]

        try:
            response = self.session.get(url, params=params)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"请求失败: {e}")
            return []
        except json.JSONDecodeError as e:
            logger.error(f"JSON解析失败: {e}")
            return []

    def get_all_projects_paginated(self, **kwargs) -> List[Dict]:
        """
        获取所有项目（分页获取）
        
        Args:
            **kwargs: 查询参数
        
        Returns:
            所有项目列表
        """
        all_projects = []
        page = 1
        per_page = kwargs.get('per_page', 100)

        while True:
            kwargs_copy = kwargs.copy()
            kwargs_copy.update({'page': page, 'per_page': per_page})

            projects = self.get_all_projects(**kwargs_copy)

            if not projects:
                break

            all_projects.extend(projects)
            logger.info(f"已获取第 {page} 页，累计 {len(all_projects)} 个项目")

            if len(projects) < per_page:
                break

            page += 1
            time.sleep(random.uniform(0.1, 0.3))

        return all_projects

    def projects_to_dataframe(self, projects_data: List[Dict]) -> pd.DataFrame:
        """
        将项目数据转换为DataFrame
        
        Args:
            projects_data: 项目数据列表
        
        Returns:
            DataFrame格式的项目数据
        """
        if not projects_data:
            return pd.DataFrame()

        # 提取关键字段
        data = []
        for project in projects_data:
            try:
                data.append({
                    'id': project.get('id'),
                    'name': project.get('name', ''),
                    'path': project.get('path', ''),
                    'path_with_namespace': project.get('path_with_namespace', ''),
                    'description': project.get('description', ''),
                    'default_branch': project.get('default_branch', ''),
                    'visibility': project.get('visibility', ''),
                    'web_url': project.get('web_url', ''),
                    'ssh_url_to_repo': project.get('ssh_url_to_repo', ''),
                    'http_url_to_repo': project.get('http_url_to_repo', ''),
                    'created_at': project.get('created_at', ''),
                    'last_activity_at': project.get('last_activity_at', ''),
                    'creator_id': project.get('creator_id'),
                    'namespace': project.get('namespace', {}).get('name', '') if project.get('namespace') else '',
                    'namespace_path': project.get('namespace', {}).get('path', '') if project.get('namespace') else '',
                    'star_count': project.get('star_count', 0),
                    'forks_count': project.get('forks_count', 0),
                    'open_issues_count': project.get('open_issues_count', 0),
                    'empty_repo': project.get('empty_repo', False),
                    'archived': project.get('archived', False)
                })
            except Exception as e:
                logger.warning(f"处理项目数据时出错: {e}")
                continue

        return pd.DataFrame(data)

    def get_all_projects_dataframe(self, group_id: Optional[str] = None, **kwargs) -> pd.DataFrame:
        """
        获取所有项目并返回DataFrame
        
        Args:
            group_id: 群组ID（可选）
            **kwargs: 查询参数
        
        Returns:
            项目DataFrame
        """
        if group_id:
            # 获取群组项目
            all_projects = []
            page = 1
            per_page = kwargs.get('per_page', 100)

            while True:
                kwargs_copy = kwargs.copy()
                kwargs_copy.update({'page': page, 'per_page': per_page})

                projects = self.get_group_projects(group_id, **kwargs_copy)

                if not projects:
                    break

                all_projects.extend(projects)
                logger.info(f"已获取群组 {group_id} 第 {page} 页，累计 {len(all_projects)} 个项目")

                if len(projects) < per_page:
                    break

                page += 1
                time.sleep(random.uniform(0.1, 0.3))
        else:
            # 获取所有项目
            all_projects = self.get_all_projects_paginated(**kwargs)

        return self.projects_to_dataframe(all_projects)

    def get_project_info(self, project_id: str) -> Dict:
        """
        获取单个项目的详细信息
        
        Args:
            project_id: 项目ID或路径
        
        Returns:
            项目详细信息
        """
        encoded_project_id = quote_plus(str(project_id))
        url = f"{self.base_url}/projects/{encoded_project_id}"

        try:
            response = self.session.get(url)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"获取项目信息失败: {e}")
            return {}


class GitLabUsersCollector:
    """GitLab用户信息收集器（从原gitlab_users_collector.py迁移）"""

    def __init__(self, gitlab_url: str, access_token: str):
        """
        初始化GitLab用户收集器
        
        Args:
            gitlab_url: GitLab服务器地址
            access_token: GitLab访问令牌
        """
        self.gitlab_url = gitlab_url.rstrip('/')
        self.access_token = access_token
        self.headers = {
            'Private-Token': access_token,
            'Content-Type': 'application/json'
        }

    def test_connection(self) -> bool:
        """
        测试GitLab连接
        
        Returns:
            bool: 连接是否成功
        """
        try:
            url = f"{self.gitlab_url}/api/v4/user"
            response = requests.get(url, headers=self.headers, timeout=10)

            if response.status_code == 200:
                user_info = response.json()
                is_admin = user_info.get('is_admin', False)
                logger.info(
                    f"连接成功！当前用户: {user_info.get('name', 'Unknown')} ({user_info.get('username', 'Unknown')})")
                logger.info(f"管理员权限: {'是' if is_admin else '否'}")

                if not is_admin:
                    logger.warning("当前访问令牌没有管理员权限，可能无法获取用户的私有邮箱地址")
                    logger.info("建议使用管理员账户的访问令牌以获取完整的用户信息")

                return True
            else:
                logger.error(f"连接失败，状态码: {response.status_code}, 响应: {response.text}")
                return False

        except Exception as e:
            logger.error(f"连接测试异常: {str(e)}")
            return False

    def check_admin_privileges(self) -> bool:
        """
        检查当前访问令牌是否具有管理员权限
        
        Returns:
            bool: 是否具有管理员权限
        """
        try:
            url = f"{self.gitlab_url}/api/v4/user"
            response = requests.get(url, headers=self.headers, timeout=10)

            if response.status_code == 200:
                user_info = response.json()
                return user_info.get('is_admin', False)
            else:
                return False

        except Exception as e:
            logger.error(f"检查管理员权限异常: {str(e)}")
            return False

    def get_all_users(self) -> List[Dict]:
        """
        获取所有用户列表
        
        Returns:
            List[Dict]: 用户列表
        """
        users = []
        page = 1
        per_page = 100

        while True:
            url = f"{self.gitlab_url}/api/v4/users"
            params = {
                'page': page,
                'per_page': per_page,
                'active': True  # 只获取活跃用户
            }

            try:
                response = requests.get(url, headers=self.headers, params=params, timeout=30)
                response.raise_for_status()

                page_users = response.json()
                if not page_users:
                    break

                users.extend(page_users)
                logger.info(f"已获取第 {page} 页用户，当前总数: {len(users)}")

                if len(page_users) < per_page:
                    break

                page += 1
                time.sleep(0.1)  # 避免API限制

            except Exception as e:
                logger.error(f"获取用户列表失败: {str(e)}")
                break

        logger.info(f"总共获取到 {len(users)} 个用户")
        return users

    def get_user_details(self, user_id: int) -> Optional[Dict]:
        """
        获取用户详细信息
        
        Args:
            user_id: 用户ID
        
        Returns:
            Optional[Dict]: 用户详细信息，失败时返回None
        """
        try:
            url = f"{self.gitlab_url}/api/v4/users/{user_id}"
            response = requests.get(url, headers=self.headers, timeout=10)
            response.raise_for_status()

            user_data = response.json()

            # 提取关键信息
            user_info = {
                'id': user_data.get('id'),
                'username': user_data.get('username', ''),
                'name': user_data.get('name', ''),
                'state': user_data.get('state', ''),
                'avatar_url': user_data.get('avatar_url', ''),
                'web_url': user_data.get('web_url', ''),
                'created_at': user_data.get('created_at', ''),
                'bio': user_data.get('bio', ''),
                'location': user_data.get('location', ''),
                'public_email': user_data.get('public_email', ''),
                'skype': user_data.get('skype', ''),
                'linkedin': user_data.get('linkedin', ''),
                'twitter': user_data.get('twitter', ''),
                'website_url': user_data.get('website_url', ''),
                'organization': user_data.get('organization', ''),
                'job_title': user_data.get('job_title', ''),
                'last_sign_in_at': user_data.get('last_sign_in_at', ''),
                'confirmed_at': user_data.get('confirmed_at', ''),
                'last_activity_on': user_data.get('last_activity_on', ''),
                'color_scheme_id': user_data.get('color_scheme_id', ''),
                'projects_limit': user_data.get('projects_limit', 0),
                'current_sign_in_at': user_data.get('current_sign_in_at', ''),
                'identities': user_data.get('identities', []),
                'can_create_group': user_data.get('can_create_group', False),
                'can_create_project': user_data.get('can_create_project', False),
                'two_factor_enabled': user_data.get('two_factor_enabled', False),
                'external': user_data.get('external', False),
                'private_profile': user_data.get('private_profile', False),
                'commit_email': user_data.get('commit_email', ''),
                'private_email': user_data.get('email', ''),  # 私有邮箱（需要管理员权限）
            }

            # 处理邮箱字段：优先使用public_email，如果为空则尝试使用email字段
            public_email = user_data.get('public_email', '')
            private_email = user_data.get('email', '')

            if public_email:
                user_info['email'] = public_email
            elif private_email:
                user_info['email'] = private_email
            else:
                user_info['email'] = ''

            return user_info

        except Exception as e:
            logger.error(f"获取用户 {user_id} 详细信息失败: {str(e)}")
            return None

    def export_to_csv(self, users: List[Dict], filename: str = None) -> str:
        """
        导出用户数据到CSV文件
        
        Args:
            users: 用户数据列表
            filename: 输出文件名，如果为None则自动生成
        
        Returns:
            str: 输出文件路径
        """
        if not users:
            logger.warning("没有用户数据可导出")
            return ""

        if filename is None:
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"gitlab_users_{timestamp}.csv"

        try:
            # 获取所有字段名
            fieldnames = list(users[0].keys())

            with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                writer.writeheader()

                for user in users:
                    # 处理列表类型的字段
                    processed_user = user.copy()
                    for key, value in processed_user.items():
                        if isinstance(value, list):
                            processed_user[key] = json.dumps(value, ensure_ascii=False)

                    writer.writerow(processed_user)

            logger.info(f"用户数据已导出到: {filename}")
            return filename

        except Exception as e:
            logger.error(f"导出CSV文件失败: {str(e)}")
            return ""

    def export_to_json(self, users: List[Dict], filename: str = None) -> str:
        """
        导出用户数据到JSON文件
        
        Args:
            users: 用户数据列表
            filename: 输出文件名，如果为None则自动生成
        
        Returns:
            str: 输出文件路径
        """
        if not users:
            logger.warning("没有用户数据可导出")
            return ""

        if filename is None:
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"gitlab_users_{timestamp}.json"

        try:
            with open(filename, 'w', encoding='utf-8') as jsonfile:
                json.dump(users, jsonfile, ensure_ascii=False, indent=2)

            logger.info(f"用户数据已导出到: {filename}")
            return filename

        except Exception as e:
            logger.error(f"导出JSON文件失败: {str(e)}")
            return ""

    def print_user_summary(self, users: List[Dict]):
        """
        打印用户统计摘要
        
        Args:
            users: 用户数据列表
        """
        if not users:
            logger.info("没有用户数据")
            return

        total_users = len(users)
        active_users = len([u for u in users if u.get('state') == 'active'])
        users_with_email = len([u for u in users if u.get('email')])
        users_with_public_email = len([u for u in users if u.get('public_email')])
        external_users = len([u for u in users if u.get('external', False)])

        logger.info("=== 用户统计摘要 ===")
        logger.info(f"总用户数: {total_users}")
        logger.info(f"活跃用户数: {active_users}")
        logger.info(f"有邮箱地址的用户: {users_with_email}")
        logger.info(f"有公开邮箱的用户: {users_with_public_email}")
        logger.info(f"外部用户数: {external_users}")

        # 按状态统计
        states = {}
        for user in users:
            state = user.get('state', 'unknown')
            states[state] = states.get(state, 0) + 1

        logger.info("\n按状态统计:")
        for state, count in states.items():
            logger.info(f"  {state}: {count}")


# 兼容性函数
def get_random_gitlab_token():
    """获取随机GitLab令牌（兼容性函数）"""
    tokens = [
        "glpat-xxxxxxxxxxxxxxxxxx",  # 示例令牌
    ]
    return random.choice(tokens)
